/*
 * @Author: Wangjun
 * @Date: 2021-06-02 10:11:52
 * @LastEditTime: 2024-07-27 09:47:15
 * @LastEditors: wangjun haodreams@163.com
 * @Description:格式美化
 * @FilePath: \libs\easy\beautify.go
 * hnxr
 */
package easy

import (
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"
)

const (
	KB = 1024
	MB = 1024 * KB
	GB = 1024 * MB
	TB = 1024 * GB
	PB = 1024 * TB
)

// Duration to e.g. 432ms or 12s, human readable translation
func BeautifyDuration(d time.Duration) string {
	u, ms, s := uint64(d), uint64(time.Millisecond), uint64(time.Second)
	if d < 0 {
		u = -u
	}
	switch {
	case u < ms:
		return "0"
	case u < s:
		return strconv.FormatUint(u/ms, 10) + "ms"
	default:
		return strconv.FormatUint(u/s, 10) + "s"
	}
}

// 美化数字
func BeautifyFloat(f float64, prec int) string {
	v := math.Abs(f)
	switch {
	case v < 0:
		return fmt.Sprintf("%.3f", f)
	case v < 10:
		return fmt.Sprintf("%.3f", f)
	case v < 100:
		return fmt.Sprintf("%.2f", f)
	case v < 10000:
		return fmt.Sprintf("%.2f", f)
	case math.IsNaN(v):
		return "-"
	}
	return fmt.Sprintf("%.3f万", f/10000)
}

func Float(f float64, prec int) string {
	str := strconv.FormatFloat(f, 'f', prec, 64)
	// 查找小数点的位置。
	decimalIndex := len(str)
	if dotIndex := strings.IndexByte(str, '.'); dotIndex >= 0 {
		decimalIndex = dotIndex
	}
	// 如果存在小数点，那么移除所有末尾的零和小数点。
	if decimalIndex < len(str) {
		// 移除末尾的零。
		i := len(str) - 1
		for str[i] == '0' {
			i--
		}
		str = str[:i]

		// 如果最后一个字符是小数点，则移除它。
		if str[len(str)-1] == '.' {
			str = str[:len(str)-1]
		}
	}

	return str
}

/**
 * @description: 美化易读的数字
 * @param {int64} s
 * @return {*}
 */
func BeautifySize(s int64) string {
	switch {
	case s < KB:
		return strconv.FormatInt(s, 10) + "B"
	case s < MB:
		return strconv.FormatFloat(float64(s)/1024.0, 'f', 2, 64) + "KB"
	default:
		return strconv.FormatFloat(float64(s)/1024.0/1024.0, 'f', 2, 64) + "MB"
	}
}

/**
 * @description: 解析字节单位
 * @param {string} s
 * @return {*}
 */
func ParseSize(s string) (int64, error) {
	s = strings.ToUpper(s)
	s = strings.TrimSpace(s)
	s = strings.TrimSuffix(s, "B")
	switch {
	case strings.HasSuffix(s, "B"):
		s = strings.TrimSuffix(s, "B")
		s = strings.TrimSpace(s)
		return strconv.ParseInt(s, 10, 64)
	case strings.HasSuffix(s, "K"):
		s = strings.TrimSuffix(s, "K")
		s = strings.TrimSpace(s)
		val, err := strconv.ParseFloat(s, 64)
		val *= KB
		return int64(val), err
	case strings.HasSuffix(s, "M"):
		s = strings.TrimSuffix(s, "M")
		s = strings.TrimSpace(s)
		val, err := strconv.ParseFloat(s, 64)
		val *= MB
		return int64(val), err
	case strings.HasSuffix(s, "G"):
		s = strings.TrimSuffix(s, "G")
		s = strings.TrimSpace(s)
		val, err := strconv.ParseFloat(s, 64)
		val *= GB
		return int64(val), err
	case strings.HasSuffix(s, "T"):
		s = strings.TrimSuffix(s, "T")
		s = strings.TrimSpace(s)
		val, err := strconv.ParseFloat(s, 64)
		val *= TB
		return int64(val), err
	}
	s = strings.TrimSpace(s)
	return strconv.ParseInt(s, 10, 64)
}
